package com.qiwenshare.file.util;


import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.qiwenshare.file.config.minio.MinioConfig;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Component
@Slf4j
public class MinioUtil {
        @Autowired
        private MinioConfig prop;

        @Resource
        private MinioClient minioClient;


        /**
         * 查看存储bucket是否存在
         * @return boolean
         */
        public Boolean bucketExists(String bucketName) {
                Boolean found;
                try {
                        found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
                } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                }
                return found;
        }

        /**
         * 创建存储bucket
         * @return Boolean
         */
        public Boolean makeBucket(String bucketName) {
                try {
                        minioClient.makeBucket(MakeBucketArgs.builder()
                                .bucket(bucketName)
                                .build());
                } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                }
                return true;
        }
        /**
         * 删除存储bucket
         * @return Boolean
         */
        public Boolean removeBucket(String bucketName) {
                try {
                        minioClient.removeBucket(RemoveBucketArgs.builder()
                                .bucket(bucketName)
                                .build());
                } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                }
                return true;
        }
        /**
         * 获取全部bucket
         */
        public List<Bucket> getAllBuckets() {
                try {
                        List<Bucket> buckets = minioClient.listBuckets();
                        return buckets;
                } catch (Exception e) {
                        e.printStackTrace();
                }
                return null;
        }



        /**
         * 文件上传
         *
         * @param file 文件
         * @return Boolean
         */
        SimpleDateFormat dataFormat = new SimpleDateFormat("yyyy-MM/dd");
        public String upload(MultipartFile file) {
                String originalFilename = file.getOriginalFilename();
                if (StringUtils.isBlank(originalFilename)){
                        throw new RuntimeException();
                }

                String fileName =  UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
                String objectName = dataFormat.format(System.currentTimeMillis()) + "/" + fileName;
                InputStream inputStream = null;
                try {
                        inputStream = file.getInputStream();
                        PutObjectArgs objectArgs =
                                PutObjectArgs.builder()
                                        .bucket(prop.getBucketName())
                                        .object(objectName)
                                        .stream(inputStream, file.getSize(), -1)
                                        .contentType(file.getContentType()).build();
                        //文件名称相同会覆盖
                        minioClient.putObject(objectArgs);

                } catch (Exception e) {
                        e.printStackTrace();
                        return null;
                } finally {
                        if(inputStream != null) {
                                try{
                                        inputStream.close();
                                } catch (Exception e) {

                                }

                        }
                }
                return objectName;
        }

        /**
         * 预览图片
         * @param fileName
         * @return
         */
        public String preview(String fileName){
                // 查看文件地址new GetPresignedObjectUrlArgs().builder();
                GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket("miniofile").object(fileName).method(Method.GET).build();
                try {
                        String url = minioClient.getPresignedObjectUrl(build);
                        return url;
                } catch (Exception e) {
                        e.printStackTrace();
                }

                return null;
        }
        public String previewImage(String fileName){
                // 查看文件地址new GetPresignedObjectUrlArgs().builder();
                GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(prop.getBucketName()).object(fileName).method(Method.GET).build();
                try {
                        String url = minioClient.getPresignedObjectUrl(build);
                        return url;
                } catch (Exception e) {
                        e.printStackTrace();
                }

                return null;
        }
        /**
         * 判断文件是否存在
         *
         * @param objectName 文件名称, 如果要带文件夹请用 / 分割, 例如 /help/index.html
         * @return true存在, 反之
         */
        public Boolean checkFileIsExist(String objectName) {
                try {
                        minioClient.statObject(
                                StatObjectArgs.builder().bucket(prop.getImageBucketName()).object(objectName).build()
                        );
                } catch (Exception e) {
                        return false;
                }
                return true;

        }


        /**
         * 文件下载
         * @param fileName 文件名称
         * @param res response
         * @return Boolean
         */
        public void download(String fileName, HttpServletResponse res) {
                GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(prop.getBucketName())
                        .object(fileName).build();
                try (GetObjectResponse response = minioClient.getObject(objectArgs)){
                        byte[] buf = new byte[1024];
                        int len;
                        try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()){
                                while ((len=response.read(buf))!=-1){
                                        os.write(buf,0,len);
                                }
                                os.flush();
                                byte[] bytes = os.toByteArray();
                                res.setCharacterEncoding("utf-8");
                                // 设置强制下载不打开
                                // res.setContentType("application/force-download");
                                res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
                                try (ServletOutputStream stream = res.getOutputStream()){
                                        stream.write(bytes);
                                        stream.flush();
                                }
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                }
        }

        /**
         * 查看文件对象
         * @return 存储bucket内文件对象信息
         */
        public List<Item> listObjects() {
                Iterable<Result<Item>> results = minioClient.listObjects(
                        ListObjectsArgs.builder().bucket(prop.getBucketName()).build());
                List<Item> items = new ArrayList<>();
                try {
                        for (Result<Item> result : results) {
                                items.add(result.get());
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                        return null;
                }
                return items;
        }

        /**
         * 删除
         * @param fileName
         * @return
         * @throws Exception
         */
        public boolean remove(String fileName){
                try {
                        minioClient.removeObject( RemoveObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build());
                }catch (Exception e){

                        return false;
                }
                return true;
        }



}

